<?php

declare(strict_types=1);

namespace App\Resource\Service;

use App\Activity\Model\ActivityGoodsModel;
use App\Activity\Model\ActivityModel;
use App\Activity\Service\ActivityService;
use App\Common\Constants\ErrorCode;
use App\Common\Service\BaseService;
use App\Common\Service\Bc;
use App\Common\Service\MiniAppService;
use App\Order\Model\OrderGoodsModel;
use App\Order\Service\OrderService;
use App\Resource\Event\UpdateGoodsCache;
use App\Resource\Model\AppGoodsModel;
use App\Resource\Model\CartModel;
use App\Resource\Model\CategoryModel;
use App\Resource\Model\CookbookGoodsModel;
use App\Resource\Model\CrdCategoryModel;
use App\Resource\Model\GoodsListModel;
use App\Resource\Model\GoodsModel;
use App\Resource\Model\ShopModel;
use App\Resource\Model\SystemModel;
use App\Resource\Repository\RepositoryFactory;
use App\Third\Model\ShopLsyGoodsStockModel;
use App\Third\Model\ShopSchemeGoodsPriceModel;
use App\Third\Service\Lsy\LsyShopGoodsPriceService;
use App\Third\Service\Lsy\LsyShopSchemeService;
use App\Third\Service\Lsy\PullLsyStockService;
use Exception;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Context;
use Psr\EventDispatcher\EventDispatcherInterface;

class GoodsService extends BaseService
{

    /**
     * 商品状态 0禁用，1启用
     */
    const GOODS_STATUS_0 = 0;
    const GOODS_STATUS_1 = 1;
    /**
     * 删除状态 0未删除，1已删除
     */
    const GOODS_IS_DELETED_0 = 0;
    const GOODS_IS_DELETED_1 = 1;
    /**
     * 商品种类 0、标品  1、非标品
     */
    const GOODS_SCANT_0 = 0;
    const GOODS_SCANT_1 = 1;
    /*
     * 是否读库存0读1不读
     * */
    const STOCK_TYPE_0 = 0;
    const STOCK_TYPE_1 = 1;
    /**
     * 库存状态 0不读，1读取
     */
    const GOODS_READ_POS_STOCK_0 = 0;
    const GOODS_READ_POS_STOCK_1 = 1;

    /**
     * 读取POS价格状态 0不读，1读取
     */
    const GOODS_READ_POS_PRICE_0 = 0;
    const GOODS_READ_POS_PRICE_1 = 1;
    /**
     * @Inject()
     * @var Bc
     */
    protected $bc;

    /**
     * @Inject()
     * @var MiniAppService
     */
    protected $miniAppService;

    protected $goodsRepository;

    public function __construct(RepositoryFactory $repoFactory)
    {
        parent::__construct();
        $this->goodsRepository = $repoFactory->getRepository("goods");
    }

    /**
     * @param array $where
     * @param int $perPage
     * @param array|string[] $field
     *
     * @return array
     */
    public function getGoodsList(array $where, int $perPage = 15, array $field = ['*'])
    {
        // 若没有状态，默认查询上架商品
        $status = in_array($where['status'] ?? null, ['0', '1']) ? $where['status'] : '1';
        $query = GoodsModel::query();
        // 这个条件每次都要加上
        $query->where('store_goods.status', '=', $status);
        $query->where('store_goods.is_deleted', '=', 0);
        //只有上架状态，才判断及时达和次日达，二者必选其一
        if ($status != 0) {
            //商品类别：0为及时达，1为次日达
            $shopType = $where['shop_type'] ?? 0;
            if ($shopType == 0) {
                $query->where('store_goods.is_today', '=', '1');
            } elseif ($shopType == 1) {
                $query->where('store_goods.is_next_day', '=', '1');
            }
        }
        if (!empty($where['title'])) {
            if (is_numeric(trim($where['title']))) {
                $query->where('store_goods.id', '=', trim($where['title']));
            } else {
                $query->whereRaw('INSTR(store_goods.title, ?) > 0', [$where['title']]);
            }
        }
        !empty($where['id']) && $query->where('store_goods.id', '=', $where['id']);
        !empty($where['cate_id']) && $query->where('store_goods.cate_id', '=', $where['cate_id']);
        !empty($where['crd_cate_id']) && $query->where('store_goods.crd_cate_id', '=', $where['crd_cate_id']);
        if (array_key_exists('is_home', $where) && $where['is_home'] != '') {
            $query->where('store_goods.is_home', '=', $where['is_home']);
        }
        if (array_key_exists('hot_id', $where) && $where['hot_id'] != '') {
            $query->where('store_goods.hot_id', '=', $where['hot_id']);
        }
        if (array_key_exists('scant_id', $where) && $where['scant_id'] != '') {
            $query->where('store_goods.scant_id', '=', $where['scant_id']);
        }
        if (!empty($where['goods_crm_code_status'])) {
            if ($where['goods_crm_code_status'] == 1) {
                $query->whereIn('store_goods.goods_crm_code', ['', null]);
            } elseif ($where['goods_crm_code_status'] == 2) {
                $query->where('store_goods.goods_crm_code', '<>', null)
                    ->where('store_goods.goods_crm_code', '<>', '');
            }
        }
        if (!empty($where['wx_crm_code_status'])) {
            if ($where['wx_crm_code_status'] == 1) {
                $query->whereIn('store_goods.wx_crm_code', ['', null]);
            } elseif ($where['wx_crm_code_status'] == 2) {
                $query->where('store_goods.wx_crm_code', '<>', '')
                    ->where('store_goods.wx_crm_code', '<>', null);
            }
        }
        if (!empty($where['kz_goods_id_status'])) {
            if ($where['kz_goods_id_status'] == 1) {
                $query->whereIn('store_goods.kz_goods_id', ['', null]);
            } elseif ($where['kz_goods_id_status'] == 2) {
                $query->where('store_goods.kz_goods_id', '<>', '')
                    ->where('store_goods.kz_goods_id', '<>', null);
            }
        }
        $list = $query
            ->leftJoin('store_goods_list as list', 'store_goods.id', '=', 'list.goods_id')
            ->selectRaw(
                'store_goods.id,
                   store_goods.logo,
                   store_goods.cate_id,
                   store_goods.crd_cate_id,
                   store_goods.title,
                   store_goods.is_home,
                   store_goods.ratio,
                   store_goods.hot_id,
                   store_goods.goods_crm_code,
                   store_goods.wx_crm_code,
                   store_goods.kz_goods_id,
                   store_goods.scant_id,
                   store_goods.sort,
                   store_goods.member_goods,
                   store_goods.create_at,
                   store_goods.status,
                   store_goods.lsy_unit_name,
                   list.goods_spec,
                   list.price_selling,
                   list.member_price,
                   list.member_func,
                   list.discount,
                   list.price_market,
                   list.commission,
                   list.number_stock'
            )
            ->where('list.status', 1)
            ->latest('store_goods.sort')
            ->Paginate($perPage);
        if ($list->isEmpty()) {
            return ['code' => ErrorCode::SUCCESS, 'data' => $list];
        } else {
            $listArr = $list->toArray()['data'];
        }

        // 以下代码可以在上述表查询处通过连表得到相同结果，考虑到连表数量过多，因此暂时用一下写法测试
        $cateIdBelongGoodsId = array_column($listArr, 'cate_id', 'id');
        $cateId = array_values($cateIdBelongGoodsId);
        $cateName = CategoryModel::query()->whereIn('id', $cateId)->select(['id', 'title'])->get()->toArray();
        $cateNameArr = array_column($cateName, 'title', 'id');

        $crdCateIdBelongGoodsId = array_column($listArr, 'crd_cate_id', 'id');
        $crdCateId = array_values($crdCateIdBelongGoodsId);
        $cateName = CrdCategoryModel::query()->whereIn('id', $crdCateId)->select(['id', 'title'])->get()->toArray();
        $crdCateNameArr = array_column($cateName, 'title', 'id');

        foreach ($listArr as $key => $vo) {
            //为分类名称赋值
            $list[$key]['category'] = $cateNameArr[$vo['cate_id']] ?? '未分类';
            $list[$key]['crd_category'] = $crdCateNameArr[$vo['crd_cate_id']] ?? '未分类';
            if ($vo['member_func'] == 2) {
                //按固定会员价
                $list[$key]['member_price'] = $vo['member_price'];
            } elseif ($vo['member_func'] == 1) {
                //按折扣计算会员价
                $list[$key]['member_price'] = $vo['price_selling'] * $vo['discount'];
            } else {
                $list[$key]['member_price'] = '';
            }
            $list[$key]['category'] = $list[$key]['category'] ?? '默认分类';
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }
    /**
     * 参加秒杀活动商品ID
     * @param int $shop_id
     * @return array
     */
    public static function getSecKillActivityGoodsByShopId(int $shop_id)
    {
        $activityIdArr = ActivityModel::query()->where('activityType',4)
            ->whereDate('begin_date',date('Y-m-d',time()))
            ->where('status','<>',0)
            ->where('is_deleted',0)
            ->whereRaw('FIND_IN_SET(?,shop_ids)', [$shop_id])
            ->pluck('activityID');
        return array_filter(array_unique(ActivityGoodsModel::query()->whereIn('activityID', $activityIdArr)->pluck('goods_id')->toArray()));
    }

    /**
     * 活动关联商品
     * @param int $activityId
     * @param int $type 0团购，1限购，2专题，3秒杀
     * @return array
     */
    public function activityGoods(int $activityId, int $type)
    {
        $perPage = !empty($perPage) ? (int)($perPage) : 5000;
        $bindGoods = ActivityGoodsModel::query()
            ->leftJoin('store_goods as goods', 'store_activity_goods.goods_id', '=', 'goods.id')
            ->leftjoin('store_goods_cate as cate', 'goods.cate_id', '=', 'cate.id')
            ->leftjoin('store_goods_list as list', 'goods.id', '=', 'list.goods_id')
            ->where(['store_activity_goods.activityID' => $activityId])
            ->where('store_activity_goods.is_deleted', 0)
            ->selectRaw(
                'store_activity_goods.goods_id,
                    store_activity_goods.costprice,
                    store_activity_goods.price_selling as activity_price_selling,
                    store_activity_goods.stock,
                    store_activity_goods.goods_cate,
                    store_activity_goods.per_can_buy_num,
                    store_activity_goods.free_num,
                    store_activity_goods.need_invited_num,
                    goods.logo,
                    goods.status,
                    goods.lsy_unit_name,
                    goods.title as goods_title,
                    goods.member_goods,
                    cate.title as category,
                    list.goods_spec,
                    list.member_func,
                    list.discount,
                    list.member_price,
                    list.price_selling,
                    store_activity_goods.commission
                ')
            ->Paginate($perPage);
        foreach ($bindGoods as $key => $val) {
            if ($val->member_func == 1) {
                $bindGoods[$key]['member_price'] = $this->bc->math_mul($val->price_selling, $val->discount);
            }
            //团购、限购和秒杀使用活动商品表里面的价格和库存，专题活动使用商品表里面的价格
            if ($type == 2) {
                $bindGoods[$key]['price_selling'] = $val->price_selling;
            } else {
                $bindGoods[$key]['price_selling'] = $val->activity_price_selling;
            }
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => $bindGoods];
    }

    /**
     * 根据平台商品Id获取商品全量信息(包含及时达、次日达)
     * @param int $id
     * @param array $field
     *
     * @return array
     */
    public function getInfoById(int $id, array $field)
    {
        $goods = GoodsModel::query()->where('id', $id)->select($field[0])->first();
        if (!$goods) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $goods['is_next_day'] = intval($goods['is_next_day']);
        $goods['is_today'] = intval($goods['is_today']);
        $goods = $goods->toArray();
        $goodsList = GoodsListModel::query()->where('goods_id', $goods['id'])->select($field[1])->first();
        if (!$goodsList) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $goodsList = $goodsList->toArray();
        $goodsSpecArr = explode('/', $goodsList['goods_spec']);
        if ($goods['scant_id'] == 1) {
            //非标品，克数读取 ratio 字段
            $goodsList['spec'] = $goods['ratio'];
        } else {
            $goodsList['spec'] = $goodsSpecArr[0];
        }
        $goodsList['unit'] = $goodsSpecArr[1];
        // 商品对应的菜谱及菜谱商品（菜谱目前先不展示）
//        $goodsWithCookbook = CookbookGoodsModel::query()->where('goods_id', $id)->get();
//        if (!$goodsWithCookbook->isEmpty()) {
//            $arr = [];
//            foreach ($goodsWithCookbook as $key => $val) {
//                $arr[$val['cookbook_id']][] = $val['goods_in_cookbook'];
//            }
//            $cookbook = $arr;
//        } else {
//            $cookbook = [];
//        }
        $res = array_merge($goods, $goodsList);
//        $res['cookbook'] = $cookbook;
        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }

    /**
     * @param array $params
     * @return array
     */
    public function add(array $params)
    {
        //会员商品检测
        if ($params['member_goods'] == 1) {
            $group_id = 2;
        } else {
            $group_id = 0;
        }
        $ratio = 0;
        //标品非标品检测
        if ($params['scant_id'] == 1) {
            //非标品，克数存到 ratio 字段中，且克数要大于 0
            if(bcmul((string)$params['spec'],'100') <= 0)  return ['code' => ErrorCode::GOODS_SPEC_ERROR];
            $ratio = $params['spec'];
        }
        if(bcmul((string)$params['price_selling'],'100') <= 0){
            return ['code' => ErrorCode::PRICE_ERROR];
        }
        try {
            DB::transaction(function () use ($params, $group_id, $ratio) {
                $res = GoodsModel::create([
                    'title' => $params['title'],
                    'introduction' => $params['introduction'] ?? '',
                    'cate_id' => $params['cate_id'] ?? null,
                    'crd_cate_id' => $params['crd_cate_id'] ?? null,
                    'err' => $params['err'] ?? '',
                    'sort' => $params['sort'] ?? '',
                    'scant_id' => $params['scant_id'],
                    'handle' => $params['handle'] ?? '',
                    'goods_crm_code' => $params['goods_crm_code'],
                    'wx_crm_code' => $params['wx_crm_code'],
                    'kz_type_id' => $params['kz_type_id'],
                    'kz_goods_id' => $params['kz_goods_id'],
                    'lsy_goods_name' => $params['lsy_goods_name'] ?? '',
                    'lsy_unit_name' => $params['lsy_unit_name'] ?? '',
                    'lsy_class_name' => $params['lsy_class_name'] ?? '',
                    'read_pos_price' => $params['read_pos_price'],
                    'member_goods' => $params['member_goods'],
                    'group_id' => $group_id,
                    'read_pos_stock' => $params['read_pos_stock'],
                    'is_home' => $params['is_home'],
                    'hot_id' => $params['hot_id'],
                    'logo' => $params['logo'],
                    'share_image' => $params['share_image'],
                    'image' => $params['image'],
                    'content' => $params['content'],
                    'status' => $params['status'] ?? 1,
                    'ratio' => $ratio,
                    'unit_id' => $params['unit_id'],
                    'is_next_day' => "{$params['is_next_day']}",
                    'is_today' => "{$params['is_today']}",
                    'safety_stock' => $params['safety_stock'] ?? 1,
                ]);

                // 商品规格字段的组合规则
                if ($params['err'] > 0) {
                    if ($params['scant_id'] == 1) {
                        $goods_spec = $params['spec'] . "g±{$params['err']}g/" . $params['unit'];
                    } else {
                        $goods_spec = $params['spec'] . "±{$params['err']}g/" . $params['unit'];
                    }
                } else {
                    if ($params['scant_id'] == 1) {

                        $goods_spec = $params['spec'] . 'g/' . $params['unit'];
                    } else {
                        $goods_spec = $params['spec'] . '/' . $params['unit'];
                    }
                }

                GoodsListModel::create([
                    'goods_id' => $res->id,
                    'goods_spec' => $goods_spec,
                    'number_virtual' => $params['number_virtual'],
                    'price_selling' => $params['price_selling'],
                    'member_func' => $params['member_func'] ?? 0,
                    'discount' => $params['discount'],
                    'member_price' => $params['member_price'],
                    'number_stock' => $params['number_stock'] ?? 0,
                    'limite_num_per_day' => $params['limite_num_per_day'] ?? null,
                    'cost_price' => $params['cost_price'] ?? null,
                    'price_market' => $params['price_market'] ?? null,
                    'commission' => $params['commission'] ?? null,
                    'goods_pick_time' => $params['goods_pick_time'] ?? null,
                ]);
                Context::set('insert_id', $res->id);
                Context::set('goods_spec', $goods_spec);
            });

        } catch (\Hyperf\Database\Exception\QueryException $e) {
            return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => '商品入库失败，请检查提交信息是否正确'];
        } catch (\Exception $e){
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }

        // 商品绑定菜谱，已弃用
//        if (!empty($params['cookbook'])) {
//            //插入菜谱中挑选的商品
//            $cookbookArr = json_decode($params['cookbook'], true);
//            $num = 0;
//            $arr = [];
//            foreach ($cookbookArr as $key => $val) {
//                foreach ($val as $k => $v) {
//                    $arr[$num]['goods_id'] = $res->id;
//                    $arr[$num]['cookbook_id'] = $key;
//                    $arr[$num]['goods_in_cookbook'] = $v;
//                    $num++;
//                }
//            }
//            CookbookGoodsModel::insert($arr);
//        }

        $insertId = Context::get('insert_id');
        $goodsSpec = Context::get('goods_spec');
        $this->redis->hSet('Goods:' . $insertId, 'title', $params['title']);
        $this->redis->hSet('Goods:' . $insertId, 'logo', $params['logo']);
        $this->redis->hSet('Goods:' . $insertId, 'goods_spec', $goodsSpec);
        $this->redis->hSet('Goods:' . $insertId, 'price_selling', $params['price_selling']);
        $this->redis->hSet('Goods:' . $insertId, 'status', 1);
        $this->eventDispatcher->dispatch(new UpdateGoodsCache('create', $insertId, $params));
        return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $insertId]];
    }

    /**
     * @param array $params
     * @return array
     */
    public function update(array $params)
    {
        $exist = GoodsModel::query()->where(['id' => $params['id']])->exists();
        if (!$exist) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        if ($params['member_goods'] == 1) {
            $group_id = 2;
        } else {
            $group_id = 0;
        }
        $ratio = 0;
        if ($params['scant_id'] == 1) {
            //非标品，克数存到 ratio 字段中，且克数要大于 0
            if(bcmul((string)$params['spec'],'100') <= 0)  return ['code' => ErrorCode::GOODS_SPEC_ERROR];
            $ratio = $params['spec'];
        }
        if(bcmul((string)$params['price_selling'],'100') <= 0){
            return ['code' => ErrorCode::PRICE_ERROR];
        }
        try {
            DB::transaction(function () use ($params, $group_id, $ratio) {
                GoodsModel::query()->where(['id' => $params['id']])->update([
                    'title' => $params['title'],
                    'introduction' => $params['introduction'] ?? '',
                    'cate_id' => $params['cate_id'] ?? null,
                    'crd_cate_id' => $params['crd_cate_id'] ?? null,
                    'err' => $params['err'] ?? '',
                    'sort' => $params['sort'] ?? '',
                    'scant_id' => $params['scant_id'],
                    'handle' => $params['handle'] ?? '',
                    'goods_crm_code' => $params['goods_crm_code'],
                    'wx_crm_code' => $params['wx_crm_code'],
                    'kz_type_id' => $params['kz_type_id'],
                    'kz_goods_id' => $params['kz_goods_id'],
                    'lsy_goods_name' => $params['lsy_goods_name'] ?? '',
                    'lsy_unit_name' => $params['lsy_unit_name'] ?? '',
                    'lsy_class_name' => $params['lsy_class_name'] ?? '',
                    'read_pos_price' => $params['read_pos_price'],
                    'group_id' => $group_id,
                    'member_goods' => $params['member_goods'],
                    'read_pos_stock' => $params['read_pos_stock'],
                    'is_home' => $params['is_home'],
                    'hot_id' => $params['hot_id'],
                    'logo' => $params['logo'],
                    'share_image' => $params['share_image'],
                    'image' => $params['image'],
                    'content' => $params['content'],
                    'status' => $params['status'],
                    'ratio' => $ratio,
                    'unit_id' => $params['unit_id'],
                    'is_next_day' => "{$params['is_next_day']}",
                    'is_today' => "{$params['is_today']}",
                    'safety_stock' => $params['safety_stock'] ?? 1,
                ]);

                if ($params['err'] > 0) {
                    if ($params['scant_id'] == 1) {
                        $goods_spec = $params['spec'] . "g±{$params['err']}g/" . $params['unit'];
                    } else {
                        $goods_spec = $params['spec'] . "±{$params['err']}g/" . $params['unit'];
                    }
                } else {
                    if ($params['scant_id'] == 1) {

                        $goods_spec = $params['spec'] . 'g/' . $params['unit'];
                    } else {
                        $goods_spec = $params['spec'] . '/' . $params['unit'];
                    }
                }
                GoodsListModel::where(['goods_id' => $params['id']])->update([
                    'goods_spec' => $goods_spec,
                    'number_virtual' => $params['number_virtual'],
                    'price_selling' => $params['price_selling'],
                    'member_func' => $params['member_func'] ?? 0,
                    'discount' => $params['discount'],
                    'member_price' => $params['member_price'],
                    'number_stock' => $params['number_stock'] ?? 0,
                    'limite_num_per_day' => $params['limite_num_per_day'] ?? null,
                    'cost_price' => $params['cost_price'] ?? null,
                    'price_market' => $params['price_market'] ?? null,
                    'commission' => $params['commission'] ?? null,
                    'goods_pick_time' => $params['goods_pick_time'] ?? null,
                ]);

                // 商品绑定菜谱，已弃用
//                if (!empty($params['cookbook'])) {
//                    CookbookGoodsModel::query()->where('goods_id', $params['id'])->delete();
//                    //插入菜谱中挑选的商品
//                    $cookbookArr = json_decode($params['cookbook'], true);
//                    $num = 0;
//                    $arr = [];
//                    foreach ($cookbookArr as $key => $val) {
//                        foreach ($val as $k => $v) {
//                            $arr[$num]['goods_id'] = $params['id'];
//                            $arr[$num]['cookbook_id'] = $key;
//                            $arr[$num]['goods_in_cookbook'] = $v;
//                            $num++;
//                        }
//                    }
//                    CookbookGoodsModel::insert($arr);
//                }

            });
        } catch (\Hyperf\Database\Exception\QueryException $e) {
            return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => '商品编辑失败，请检查提交信息是否正确'];
        } catch (\Exception $e){
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }
        $this->eventDispatcher->dispatch(new UpdateGoodsCache('update', $params['id'] , $params));
        return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $params['id']]];
    }

    /**
     * @param int $id
     * @return array
     */
    public function delete(int $id)
    {
        try {
            DB::transaction(function () use ($id) {
                GoodsModel::destroy($id);
                GoodsListModel::where(['goods_id' => $id])->delete();
            });
        } catch (\Hyperf\Database\Exception\QueryException $e){
            return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => '商品删除失败，请检查提交信息是否正确'];
        } catch (Exception $e) {
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $id]];
    }

    /**
     * 获取特定分类下的商品ID
     * @param int $cate_id
     * @return array
     */
    public function getGoodsIdsByCateId(int $cate_id)
    {
        return GoodsModel::query()
            ->where('cate_id', $cate_id)
            ->pluck('id')
            ->toArray();
    }

    /**
     * 商品销售分析
     * @param array $where
     * @param array $field
     * @return array
     */
    public function goodsLinkData(array $where = [], array $field = ['*'])
    {
        $list = GoodsModel::query()
            ->with('goodsList:goods_id,price_selling', 'goodsCate:id,title')
            ->select($field)
            ->whereIn('id', $where)
            ->get();
        $link = [];
        foreach ($list as $k => $v) {
            $link[$k]['goods_id'] = $v->id;
            $link[$k]['cate_name'] = $v->goodsCate->title;     //分类名称
            $link[$k]['original_amt'] = $v->goodsList->price_selling;  // 商品原金额
        }
        return $link;
    }

    /**
     * @param int $goodsId
     * @return bool
     */
    public function isGoodsInOrder(int $goodsId)
    {
        $exist = OrderGoodsModel::where(['goods_id' => $goodsId])->exists();
        if ($exist) {
            return true;
        }
        return false;
    }

    /**
     * @return array
     */
    public function homeHot()
    {
        $shop_id = '';
        //获取所有首页展示数据
        $hotData = $this->redis->sMembers('Home:Hot');
        $key = 0;
        foreach ($hotData as $hot) {
            //获取商品信息，查询状态是否下架
            $goods = $this->redis->hGetAll("Goods:" . $hot);
            if (empty($goods)) {
                continue;
            }
            //查询当前店铺是否在商品的下架店铺列表中
            $homePutShops = $this->redis->sIsMember($shop_id, "Goods-Put:" . $hot);
            if ($goods['status'] == 0 || $homePutShops) {
                continue;
            }
            $result[$key] = $goods;
            $result[$key]['goods_id'] = $hot;
            $key++;
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => $result];

    }

    /**
     * 获取小程序码
     * @param int $id
     * @param $type
     * @param $scene
     * @param $page
     * @return array
     * @throws \League\Flysystem\FileExistsException
     */
    public function getMiniAppCode(int $id, $type,$scene, $page)
    {
        if ($type == 1) {
            $goods = GoodsModel::query()->where('id', $id)->first();
        } else {
            $goods = ActivityGoodsModel::query()->where('id', $id)->first();
        }
        if (!$goods) {
            return ['code' => ErrorCode::NOT_EXIST, 'msg' => '商品不存在'];
        }
        if (!$goods->mini_app_code) {
            $mini_app_code = $this->miniAppService->getMiniAppCodeUrl(mb_convert_encoding($scene, 'UTF-8'), [
                'page'       => mb_convert_encoding($page, 'UTF-8'),
                "width"      => 430,
                'is_hyaline' => true,
            ]);
            $goods->update(['mini_app_code' => $mini_app_code]);
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => ['mini_app_code' => $goods->mini_app_code]];
    }

    /**
     * 获取小程序商家首页限时抢购
     * @param $shop_id
     * @return array
     */
    public function getLimitSale($shop_id)
    {
        $sale_limit = ActivityModel::query()
            ->where([
                ['end_date', '>=', date('Y-m-d H:i:s')],
                ['status', '=', 1],
                ['activityType', '=', 1],
                ['is_deleted', '=', 0],
            ])
            ->selectRaw('activityID, activityType, begin_date, end_date, activity_prams')
            ->whereRaw('FIND_IN_SET(' . $shop_id . ',shop_ids)')
            ->orderBy('begin_date')
            ->first();
        if (!$sale_limit) {
            return [];
        }
        $sale_limit = $sale_limit->toArray();
        $sale_limit['time_desc'] = ActivityModel::getSaleActivityTime($sale_limit['begin_date'], $sale_limit['end_date']);
        $sale_limit['goods_list'] = ActivityGoodsModel::query()
            ->from('store_activity_goods as ag')
            ->select([
                'g.id as goods_id',
                'ag.id as activity_goods_id',
                'g.title',
                'g.image',
                'ag.goods_spec as specs',
                'ag.group_id',
                'ag.costprice as price_market',
                'ag.price_selling',
            ])
            ->where('g.status', 1)
            ->where('g.is_deleted', 0)
            ->where('activityID', $sale_limit['activityID'])
            ->leftJoin('store_goods as g', 'ag.goods_id', '=', 'g.id')
            ->get()
            ->toArray();
        return [$sale_limit];
    }

    /**
     * 获取小程序商家首页小跑拼团数据
     * @param $shop_id
     * @param $IsNeedCount
     * @param int $page
     * @param int $limit
     * @return array
     */
    public function getShopHomeGroup($shop_id, $IsNeedCount = false, $page = 1, $limit = 6)
    {
        $model = ActivityModel::query()
            ->from('store_activity as a')
            ->select([
                'a.activityID',
                'ag.id as activity_goods_id',
                'a.image',
                'ag.goods_title as title',
                'ag.goods_id',
                'ag.goods_spec',
                'ag.price_selling',
                'ag.costprice as price_market',
                'ag.stock',
            ])
            ->leftJoin('store_activity_goods as ag', 'a.activityID', '=', 'ag.activityID')
            ->where('a.status', 1)
            ->where('a.is_deleted', 0)
            ->where('a.activityType', 0)
            ->where('a.end_date', '>', date('Y-m-d H:i:s'))
            ->whereRaw('FIND_IN_SET(' . $shop_id . ',a.shop_ids)')
            ->orderByRaw('a.sort desc,a.end_date desc');
        $totalNum = $model->count();
        $list = $model->forPage($page, $limit)->get();
        $list = $list ? $list->toArray() : [];
        if ($IsNeedCount) {
            return [
                'count' => $totalNum,
                'list' => $list,
            ];
        }
        return $list;
    }

    /**
     * 获取小程序商家首页商品列表
     * @param int $shop_id
     * @param $where
     * @param $orderBy
     * @param $page
     * @param $limit
     * @return array
     */
    public function getShopGoodsList(int $shop_id, $where = [], $limit = 6, $page = 1, $orderBy = ['sort', 'desc'])
    {
        /*$ret = $this->getGoodsListForShopByRedis('timely', $shop_id, $limit, $page);
        if ($ret['count'] > 0) return $ret;*/

        $lsy_shop_no = ShopModel::query()->where('shop_id', $shop_id)->value('lsy_shop_no');
        $stockModel =ShopLsyGoodsStockModel::query()
            ->from('qpplatformdb.shop_lsy_goods_stock')
            ->select(['itemId','surplusQuantity'])
            ->where('createShopId',$lsy_shop_no);
        $activeIds = ActivityService::getActivityGoodsByShopId($shop_id);
        $model = GoodsModel::query()
            ->from('store_goods as a')
            ->leftJoinSub($stockModel,'b',function ($join){
                $join->on('a.goods_crm_code','=','b.itemId');
            })
            ->whereNotIn('id', $activeIds)
            ->whereRaw('!FIND_IN_SET(' . $shop_id . ',shop_ids)')
            ->distinct()
            ->select(['id'])
            ->where('is_today', '1')
            ->where('is_deleted', 0)
            ->where('status', 1)
            ->where($where)
            ->orderBy($orderBy[0], $orderBy[1])
            ->orderBy('b.surplusQuantity', 'desc');
        $totalNum = $model->count();
        if ($totalNum) {
            $getArrayGoods = $model->forPage($page, $limit)->get()->toArray();
            $goodsIds =array_column($getArrayGoods,'id');
            $data = GoodsService::getGoodsInfoData($shop_id, $goodsIds, 0);
        }
        return [
            'count' => $totalNum,
            'list' => $data ?? [],
        ];
    }

    /**
     * 获取次日达自提日期
     * @return false|string
     */
    public function getTakeDate()
    {
        $deadline = SystemModel::query()->where('name', 'cut_off_time')->value('value');
        !$deadline && $deadline = '22:00';
        $takeDate = date('m/d', strtotime('+1 day'));
        if (date('H:i') > $deadline) {
            $takeDate = date('m/d', strtotime('+2 day'));
        }
        return $takeDate;
    }

    /**
     * 次日达商品
     * @param int $shop_id
     * @param int $limit
     * @param int $page
     * @param $where
     * @return array
     */
    public function nextDayGoods(int $shop_id, $limit = 6, $page = 1, $where = [])
    {
        /*$ret = $this->getGoodsListForShopByRedis('tomorrow', $shop_id, $limit, $page);
        if ($ret['count'] > 0) return $ret;*/

        $takeDate = $this->getTakeDate();
        $activeIds = GoodsService::getSecKillActivityGoodsByShopId($shop_id);
        $model = GoodsModel::query()
            ->from('store_goods as g')
            ->select([
                'g.id',
                'g.title',
                'g.group_id',
                'g.goods_crm_code',
                'g.cate_id',
                'g.crd_cate_id',
                'g.spell_num',
                'g.scant_id',
                'g.image',
                'g.ratio',
                'g.logo',
                'g.read_pos_price',
                'g.read_pos_stock',
                'g.safety_stock',
                'gl.goods_id',
                'gl.goods_spec',
                'gl.price_selling',
                'gl.price_market',
                'gl.number_stock',
                'gl.number_virtual',
                Db::raw('gl.number_sales + gl.number_virtual as number_sales'),
                Db::raw("concat(\"$takeDate\",' ',left(gl.goods_pick_time,5)) as goods_pick_time"),
            ])
            ->whereNotIn('g.id', $activeIds)
            ->whereRaw('!FIND_IN_SET(' . $shop_id . ',g.crd_shop_ids)')
            ->where('g.status', 1)
            ->where($where)
            ->where('g.is_deleted', 0)
            ->where('g.is_next_day', '1')
            ->leftJoin('store_goods_list as gl', 'gl.goods_id', '=', 'g.id')
            ->orderBy('sort', 'desc');
        $totalNum = $model->count();
        if ($totalNum) {
            $data = $model->forPage($page, $limit)->get()->toArray();
        }
        return [
            'count' => $totalNum,
            'list' => $data ?? [],
        ];
    }
    /**
     * 商品资料集合（根据店铺龙收银方案获取销售价格、根据店铺龙收银商品编码获取库存）
     * @param int $shop_id      平台店铺shop_id
     * @param array $goodsIds   平台商品id集合
     * @param int $type         0 默认读库存  1不读龙收银库存
     * @return array
     * @author Mr.Sir zhangzhiyuan
     */
    public static function getGoodsInfoData(int $shop_id, array $goodsIds, int $type = 0)
    {
        /*=======获取商品基础信息========*/
        $orderByField =implode(',',$goodsIds);
        $goodsField = ['id', 'title', 'group_id', 'goods_crm_code','spell_num', 'cate_id', 'scant_id', 'image', 'ratio', 'logo', 'read_pos_price', 'read_pos_stock', 'safety_stock', 'kz_goods_id'];
        $goodsArr = GoodsModel::query()->whereIn('id', $goodsIds)->select($goodsField)
            ->when($orderByField, function ($query, $orderByField) {
                return $query->orderByRaw("FIELD(id, " . $orderByField . ")");
            })
            ->get()->toArray();
        /*=======获取商品价格基础信息========*/
        $goodsListField = ['goods_id', 'goods_spec', 'price_selling', 'price_market', 'number_stock', 'number_virtual', 'number_sales', 'commission', 'cost_price'];
        $goodsList = GoodsListModel::query()->whereIn('goods_id', $goodsIds)->select($goodsListField)->get()->toArray();
        $GoodsListByGoodsId = array_column($goodsList, null, 'goods_id');
        //获取龙收银方案
        $lsy_shop_no = ShopModel::query()->where('shop_id', $shop_id)->value('lsy_shop_no');
        $LsySchemeId = LsyShopSchemeService::getLsySchemeIdByShopId($lsy_shop_no);
        $goodsCodeIdsArr = array_column($goodsArr, 'goods_crm_code');
        //根据店铺方案确定商品价格
        $CrmGoodsFiled = ['crm_goods_id', 'schemeID', 'price', 'stdPrice'];
        $CrmGoodsArr = ShopSchemeGoodsPriceModel::query()->whereIn('crm_goods_id', $goodsCodeIdsArr)->where(['schemeID' =>$LsySchemeId])->select($CrmGoodsFiled)->get()->toArray();
        $getPriceLsyGoodsByItemCodeArr = array_column($CrmGoodsArr, null, 'crm_goods_id');
        //根据龙收银商品ID、店铺确定平台库存
        $LsyStockGoodsFiled =['itemId','surplusQuantity'];
        $LsyStockGoodsArr = ShopLsyGoodsStockModel::query()->whereIn('itemId', $goodsCodeIdsArr)->where(['createShopId' =>$lsy_shop_no])->select($LsyStockGoodsFiled)->get()->toArray();
        $LsyGoodsStockBindItemCodeArr = array_column($LsyStockGoodsArr, null, 'itemId');
        $goodsListData = [];
        foreach ($goodsArr as $key => &$goods) {
            $goodsListData[] = array_merge($goods, $GoodsListByGoodsId[$goods['id']]);
        }
        //POS库存计算规则 读取龙收银标品非标品 POS库存*1000-安全库存(非标品安全库存*转化系数) 备注(不满足平台一份的量库存为-1)
        foreach ($goodsListData as $key => $goods) {
            if ($type == self::STOCK_TYPE_0) {
                //$LsyShopGoodsStockTask = (new CrmGoodsService())->SinglePullArchInfoStock($goods['goods_crm_code'], $shop_id)['surplusQuantity'] ?? 0;
                $getLsyGoodsStock =$LsyGoodsStockBindItemCodeArr[$goods['goods_crm_code']]['surplusQuantity']??0;
                $goodsListData[$key]['pos_goods_stock'] = bcmul((string)$getLsyGoodsStock, '1000');
                if ($goods['read_pos_stock'] == self::GOODS_READ_POS_STOCK_1) {
                    if ($goods['scant_id'] == self::GOODS_SCANT_1) {
                        $safety_stock = bcmul((string)$goods['safety_stock'], (string)$goods['ratio']);
                        $goodsListData[$key]['surplusQuantity'] = (int)bcsub((string)$goodsListData[$key]['pos_goods_stock'], (string)$safety_stock);
                        if ($goodsListData[$key]['surplusQuantity'] < $goods['ratio']) {
                            $goodsListData[$key]['surplusQuantity'] = -1;
                        }
                    } else {
                        $safety_stock = bcmul((string)$goods['safety_stock'], '1000');
                        $goodsListData[$key]['surplusQuantity'] = (int)bcsub((string)$goodsListData[$key]['pos_goods_stock'], (string)$safety_stock);
                        if ($goodsListData[$key]['surplusQuantity'] < bcmul((string)1, '1000')) {
                            $goodsListData[$key]['surplusQuantity'] = -1;
                        }
                    }
                    $goodsListData[$key]['safety_stock']=$safety_stock;
                } else {
                    $goodsListData[$key]['surplusQuantity'] = (int)bcmul((string)$goods['number_stock'], '1000');
                }
            }
            //价格计算规则 读取龙收银非标品为公斤单价需转换斤的单价 即 （公斤价/1000)*平台转换系数（备注:系数以斤为单位） 如果读取不到POS价格默认平台价格
            $PosSellingPrice =$getPriceLsyGoodsByItemCodeArr[$goods['goods_crm_code']]['price'] ?? $goods['price_selling'];
            $PosMarketPrice =$getPriceLsyGoodsByItemCodeArr[$goods['goods_crm_code']]['stdPrice'] ?? $goods['price_market'];
            if ($goods['read_pos_price'] == self::GOODS_READ_POS_PRICE_1) {
                if ($goods['scant_id'] == self::GOODS_SCANT_1) {
                    $goodsListData[$key]['price_selling'] =bcmul(bcdiv($PosSellingPrice,'1000',6),(string)$goods['ratio'],2);
                    $goodsListData[$key]['price_market'] =bcmul(bcdiv($PosMarketPrice,'1000',6),(string)$goods['ratio'],2);
                } else {
                    $goodsListData[$key]['price_selling'] =$PosSellingPrice;
                    $goodsListData[$key]['price_market'] =$PosMarketPrice;
                }
                $goodsListData[$key]['lsy_scheme_id']=$LsySchemeId;
            }
        }
        return $goodsListData;
    }
    /**
     * 次日达商品资料集合（次日达商城读取平台销售价格、读取平台库存）
     * @param array $goodsIds 平台商品id集合
     * @param array $orderBy  排序
     * @return array
     */
    public static function getCrdGoodsInfoData(array $goodsIds, $orderBy = ['create_at', 'desc'])
    {
        $goodsField = ['id', 'title', 'group_id', 'goods_crm_code', 'cate_id', 'scant_id', 'image', 'ratio', 'logo', 'read_pos_price', 'read_pos_stock', 'safety_stock', 'kz_goods_id','status','shop_ids','is_deleted','crd_cate_id','crd_shop_ids'];
        $goodsArr = GoodsModel::query()->whereIn('id', $goodsIds)->select($goodsField)->orderBy($orderBy[0], $orderBy[1])->get()->toArray();
        $goodsListField = ['goods_id', 'goods_spec', 'price_selling', 'price_market', 'number_stock', 'number_virtual', 'number_sales', 'commission', 'cost_price', 'goods_pick_time','limite_num_per_day'];
        $goodsList = GoodsListModel::query()->whereIn('goods_id', $goodsIds)->select($goodsListField)->get()->toArray();
        $GoodsListByGoodsId = array_column($goodsList, null, 'goods_id');
        $goodsListData = [];
        foreach ($goodsArr as $goods) {
            $goodsListData[] = array_merge($goods, $GoodsListByGoodsId[$goods['id']]);
        }
        return $goodsListData;
    }
    /**
     * 商品下架或删除判断 已下架或删除 返回 true 否则 false
     * @param $goodsIdsArr
     * @return bool
     */
    public static function GoodsIsFail(array $goodsIdsArr)
    {
        $goodsList = GoodsModel::query()->whereIn('id', $goodsIdsArr)->select(['status', 'is_deleted'])->get()->toArray();
        $goodsStatusArr = array_column($goodsList, 'status');
        $goodsIsDeletedArr = array_column($goodsList, 'is_deleted');
        if (in_array(self::GOODS_STATUS_0, $goodsStatusArr) || in_array(self::GOODS_IS_DELETED_1, $goodsIsDeletedArr)) {
            return true;
        }
        return false;
    }
    /**
     * 获取次日上商品详情
     * @param $id
     * @param $filed
     * @return array
     */
    public function getNextDayGoodsDetail($id, $filed = ['*'])
    {
        $takeDate = $this->getTakeDate();
        try {
            $goods = GoodsModel::query()->find($id, $filed);
            if (!$goods)
                throw new \Exception('不存在的记录');
            if ($goods->status != 1)
                throw new \Exception('商品已被删除或者被禁用');
            if ($goods->is_next_day != '1')
                throw new \Exception('该商品不是次日达商品');
            $goodsInfo = GoodsListModel::query()->where('goods_id', $id)->select([
                'goods_id',
                'goods_spec',
                'price_selling',
                'price_market',
                'limite_num_per_day',
                'number_stock',
                Db::raw('number_sales + number_virtual as spell_num'),
                Db::raw("concat(\"$takeDate\",' ',left(goods_pick_time,5)) as goods_pick_time"),
            ])->first();
            $goods = array_merge($goods->toArray(), $goodsInfo->toArray());
            return ['code' => 1, 'msg' => '获取成功', 'data' => $goods];
        } catch (\Exception $e) {
            return ['code' => 0, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 商家端App分类商品列表
     * @param $shop_id
     * @param array $where
     * @return array
     */
    public function appGoodsSortList($shop_id, array $where)
    {
        $goods = GoodsModel::query()->where($where)->whereRaw('!FIND_IN_SET(?,crd_shop_ids)', [$shop_id])->select(['id','status','crd_shop_ids'])->get();
        $goodsList = $goods? $goods->toArray():[];
        $goodsListArr = self::getCrdGoodsInfoData(array_column($goodsList, 'id'));
        $filed = ['goods_id', 'is_selected'];
        $is_selected = AppGoodsModel::query()->where('shop_id', $shop_id)->whereIn('goods_id', array_column($goodsList, 'id'))->get($filed)->toArray();
        $selected = array_column($is_selected, 'is_selected', 'goods_id');
        foreach ($goodsListArr as &$v) {
            $v['is_selected'] = $selected[$v['id']] ?? 0;
        }
        return [
            'code' => ErrorCode::SUCCESS,
            'data' => [
                'goodsListPrice' => $goodsListArr,
                'total' => count($goodsListArr),
            ],
        ];
    }

    /**
     * 次日达商品搜索
     * @param array $where
     * @param string $goodsName
     * @param int $shopId
     * @return array
     */
    public function appNextDayGoods(array $where, string $goodsName, int $shopId)
    {
        $orderBy = ['create_at', 'desc'];
        $goodsList = GoodsModel::where($where)->whereRaw('INSTR(title, ?) > 0', [$goodsName])->orderBy($orderBy[0], $orderBy[1])->select(['id','crd_shop_ids'])->get();
        if($goodsList){
            $goodsById = array_column($goodsList->toArray(),'crd_shop_ids','id');
        }else{
            return [];
        }
        $goodsList = GoodsService::getCrdGoodsInfoData(array_keys($goodsById));
        $res = AppGoodsModel::query()->where('shop_id', $shopId)->whereIn('goods_id',array_keys($goodsById))->get()->toArray();
        $is_selected = array_column($res, 'is_selected', 'goods_id');
        foreach ($goodsList as &$v) {
            $v['is_selected'] = $is_selected[$v['id']] ?? 0;
        }
        return [
                'count' => count($goodsList),
                'list' => $goodsList ??[],
        ];
    }

    /**
     * 秒杀商品详情
     * @param int $activity_goods_id
     * @param array $field
     * @param int $mid
     * @return array|\Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|\Hyperf\Database\Query\Builder|object
     */
    public function secKillGoodsDetail(int $activity_goods_id, array $field, int $mid){
        $this->container->get(ActivityService::class)->secKillGoodsClickNumRecord($activity_goods_id);
        $info = ActivityGoodsModel::query()
            ->from('store_activity_goods as ag')
            ->leftJoin('store_activity as ac', "ag.activityID", '=', 'ac.activityID')
            ->leftJoin('store_goods as g', 'ag.goods_id', '=', 'g.id')
            ->leftJoin('store_goods_list as gl', 'ag.goods_id', '=', 'gl.goods_id')
            ->leftJoin('hf_cart as cart', function ($join) use ($mid){
                $join->on('ag.id', '=', 'cart.activity_goods_id')->where('cart.mid', $mid);
            })
            ->leftJoin('hf_seckill_activity_remind as sar', function ($join) use ($mid) {
                $join->on('ag.id', '=', 'sar.activity_goods_id')->where('sar.mid', $mid);
            })
            ->selectRaw(implode(',', $field))
            ->where('ag.id', $activity_goods_id)
            ->first();
        $paidSecKillGoods = $this->container->get(OrderService::class)->getPaidSecKillGoodsNum($mid, [$activity_goods_id]);
        if (!is_null($info)){
            $time = json_decode($info->activity_prams, true);
            $start_time_ms = strtotime(date("Y-m-d {$time['start_time']}"));
            $end_time_ms = strtotime(date("Y-m-d {$time['end_time']}"));
            $info->start_time = $time['start_time'];
            $info->end_time = $time['end_time'];
            $info->image = explode('|', $info->image);
            $info->paid_num = $paidSecKillGoods[$activity_goods_id] ?? 0;
            if (time() < $start_time_ms) $info->activity_status = 0; // 即将开抢
            if (time() > $end_time_ms) $info->activity_status = 2; // 已结束、已开抢
            if ( $start_time_ms < time() and  time() < $end_time_ms) $info->activity_status = 1; // 疯抢中
            unset($info->activity_prams);
        }
        return $info ?? [];
    }

    /**
     * 获取有效、无效商品id
     * $source 1及时达 2次日达
     * @param array $goodsId
     * @param int $shopId
     * @return array
     * @author lulongfei
     */
    public function getGoodsIds(array $goodsId,int $shopId,int $source = 1)
    {
        $goods = GoodsModel::query()->whereIn('id', $goodsId);
        if ($source==1){
            $whereRawField = 'shop_ids';

        }else{
            $whereRawField = 'crd_shop_ids';

        }
        //有效
        $goodsIdEffective = $goods->where(['is_deleted' => 0, 'status' => 1])
            ->whereRaw("!FIND_IN_SET(?,{$whereRawField})", [$shopId])
            ->pluck('id')
            ->toArray();
//        //无效
//        $goodsIdInvalid = $goods
//            ->whereRaw("(FIND_IN_SET({$shopId},{$whereRawField}) OR is_deleted = 1 OR status = 0)")
//            ->pluck('id')
//            ->toArray();
        return $goodsIdEffective;
    }

    /**
     * @param array $goodsIds
     * @param array $fields
     * @return array
     * @author lulongfei
     */
    public function getGoodsLsy(array $goodsIds,array $fields)
    {
        $goodsList = GoodsModel::query()->whereIn('id', $goodsIds)
            ->select($fields)
            ->get()->toArray();
        return $goodsList;
    }

    /**
     * 商品资料集合（根据店铺龙收银方案根据店铺龙收银商品编码获取库存）
     * @param int $shop_id 平台店铺shop_id
     * @param int $goods_id 平台商品id
     * @param int $type 0 默认读库存  1不读龙收银库存
     * @return array
     * @author Mr.Sir wangchenqi
     */
    public function getGoodsInfoDataArr(int $shop_id, int $goods_id, int $type = 0)
    {
        /*=======获取商品基础信息========*/
        $goodsField = ['id', 'group_id', 'goods_crm_code', 'cate_id', 'scant_id', 'ratio', 'read_pos_stock', 'safety_stock'];
        $goodsArr = $this->goodsRepository->findFirst($goodsField,['id'=>$goods_id]);
        /*=======获取我们的商品库存========*/
        $stock = $this->goodsRepository->findSonFirst(['goods_id','number_stock'],['goods_id'=>$goods_id]);
        //获取龙收银方案
        $lsy_shop_no = ShopModel::query()->where('shop_id', $shop_id)->value('lsy_shop_no');
        //根据龙收银商品ID、店铺确定平台库存
        $LsyStockGoodsFiled = ['itemId', 'surplusQuantity'];
        $LsyStockGoodsArr = ShopLsyGoodsStockModel::query()->where(['createShopId' => $lsy_shop_no,'itemId'=>$goodsArr['goods_crm_code']])->select($LsyStockGoodsFiled)->get()->toArray();
        $LsyGoodsStockBindItemCodeArr = array_column($LsyStockGoodsArr, null, 'itemId');
        //var_dump($LsyGoodsStockBindItemCodeArr);
        $goodsListData[] = array_merge($goodsArr,$stock);
        //POS库存计算规则 读取龙收银标品非标品 POS库存*1000-安全库存(非标品安全库存*转化系数) 备注(不满足平台一份的量库存为-1)
        foreach ($goodsListData as $key => $goods) {
            if ($type == self::STOCK_TYPE_0) {
               // var_dump($LsyGoodsStockBindItemCodeArr[$goods['goods_crm_code']]['surplusQuantity']);
                $getLsyGoodsStock = $LsyGoodsStockBindItemCodeArr[$goods['goods_crm_code']]['surplusQuantity'] ?? 0;
                $goodsListData[$key]['pos_goods_stock'] = bcmul((string)$getLsyGoodsStock, '1000');
                if ($goods['read_pos_stock'] == self::GOODS_READ_POS_STOCK_1) {
                    if ($goods['scant_id'] == self::GOODS_SCANT_1) {
                        $safety_stock = bcmul((string)$goods['safety_stock'], (string)$goods['ratio']);
                        $goodsListData[$key]['surplusQuantity'] = (int)bcsub((string)$goodsListData[$key]['pos_goods_stock'], (string)$safety_stock);
                        if ($goodsListData[$key]['surplusQuantity'] < $goods['ratio']) {
                            $goodsListData[$key]['surplusQuantity'] = -1;
                        }
                    } else {
                        $safety_stock = bcmul((string)$goods['safety_stock'], '1000');
                        $goodsListData[$key]['surplusQuantity'] = (int)bcsub((string)$goodsListData[$key]['pos_goods_stock'], (string)$safety_stock);
                        if ($goodsListData[$key]['surplusQuantity'] < bcmul((string)1, '1000')) {
                            $goodsListData[$key]['surplusQuantity'] = -1;
                        }
                    }
                    $goodsListData[$key]['safety_stock'] = $safety_stock;
                } else {
                    $goodsListData[$key]['surplusQuantity'] = (int)bcmul((string)$goods['number_stock'], '1000');
                }
            }
        return $goodsListData;
        }

    }

    /**
     * redis商品数据
     * @param string $type
     * @param int $shop_id
     * @param $limit
     * @param $page
     * @return array
     * @author liule
     * @date 2021-01-27 9:50
     */
    public function getGoodsListForShopByRedis(string $type, int $shop_id, $limit, $page){
        $redis = $this->buildRedis;
        if ($type == 'timely'){
            $key0 = "timely:goods";
            $key1 = "timely:shop:{$shop_id}:goods";
            $key2 = "timely:shop:{$shop_id}:goods:sort";
            if ($redis->hLen($key0) == 0) $this->container->get(BuildGoodsService::class)->buildGoodsListToRedis('timely');
        }else{
            $key0 = "tomorrow:goods";
            $key1 = "tomorrow:shop:{$shop_id}:goods";
            $key2 = "tomorrow:shop:{$shop_id}:goods:sort";
        }
        $count = $redis->zCard($key2);
        $ret = $redis->zRange($key2, $limit * $page - $limit, $limit * $page - 1);
        if ($count > 0 && count($ret) > 0){
            $commList = $redis->hMGet($key0, $ret);
            $list = $redis->hMGet($key1, $ret);
            foreach ($commList as $goods_id => &$item){
                $item = array_merge(json_decode($item, true), json_decode($list[$goods_id],true));
            }
//            $list = array_map(fn($v) => json_decode($v, true), $list);
            return ['count' => $count,'list' => array_values($commList)];
        }else{
            return ['count' => 0,'list' => []];
        }
    }

    public function redisGoodsOp(string $event, string $type, string $attr = ''){
        $buildGoodsService = $this->container->get(BuildGoodsService::class);
        switch ($event){
            case 'build':
                if ($type == 'shop'){
                    $lsyShopMap = ShopModel::query()->pluck('lsy_shop_no', 'shop_id')->toArray();
                    if ($attr == 'timely'){
                        $ret = $buildGoodsService->buildAllShopTimelyGoodsListToRedis($lsyShopMap);
                        $msg = '构建所有店铺及时达商品缓存成功';
                    }else{
                        $ret = $buildGoodsService->buildAllShopTomorrowGoodsListToRedis($lsyShopMap);
                        $msg = '构建所有店铺次日达商品缓存成功';
                    }
                }
                if ($type == 'goods'){
                    $ret = $buildGoodsService->buildGoodsListToRedis($attr);
                    $msg = $ret['msg'];
                }
                break;
            case 'del':
                $key =  $type == 'shop' ? "{$attr}:shop:*:goods*" : "{$attr}:goods";
                $ret = $buildGoodsService->delKeys($key);
                $msg = sprintf('清空 %s-%s 商品缓存成功',$attr=='timely'?'及时达':'次日达',$type=='shop'?'每个店铺':'公共');
                break;
            default:
        }
        return ['code' => 1, 'data'=>['event' => $event,'result' => $ret], 'msg' => $msg];
    }

    public function redisLsyStockOp(string $event){
        $pullLsyStockService = $this->container->get(PullLsyStockService::class);
        switch ($event){
            case 'pull':
                $ret = $pullLsyStockService->pullLsyStockToRedis();
                $msg = '拉取龙收银库存成功';
                break;
            case 'del':
                $ret = $pullLsyStockService->delKeys();
                $msg = '清空龙收银库存缓存成功';
                break;
            case 'count':
                $ret = $pullLsyStockService->lsyStockDataCount();
                $msg = '龙收银库存缓存总条数';
                break;
            case 'data':
                $ret = $pullLsyStockService->lsyStockAllData();
                $msg = '龙收银库存缓存总数据';
                break;
            default:
        }
        return ['code' => 1, 'data'=>['event' => $event,'result' => $ret], 'msg' => $msg];
    }


}
